/*
 * @: 
 * @Version: 1.0
 * @Autor: ziwei
 * @Date: 2021-06-28 09:26:41
 * @LastEditors: ziwei
 * @LastEditTime: 2022-02-11 15:58:28
 */
class Hook{
    constructor(args){
      if(!Array.isArray(args)) args = []
      this.args = args;//把参数的数组存放在钩子内部
      this.taps = [];//存放事件函数配置对象的数组
      this.call = CALL_DELEGATE;//初始化call方法
      this.callAsync = CALL_ASYNC_DELEGATE;
      this.promise = PROMISE_DELEGATE;
      this.interceptors=[];//这就是拦截器的数组，里边放着不同拦截器对象
    }
    tap(option,fn){
        this._tap('sync',options,fn)
    }
    _tap(type,options,fn){
        if(typeof options === 'string'){
            options = {name:options}
        }
        let tapInfo = {...options,type,fn};//type=sync fn⌚️函数事件 name名称
        tabInfo = this._runRegisterInterceptors(tapInfo)
        this._insert(tapInfo)
    }
    //运行注册拦截器
    _runRegisterInterceptors(){
        for(const interceptor of this.interceptors){
            if(interceptor.register){// 如果它身上有注册拦截器的话
                let newTapInfo = Tapinterceptor.register(tapInfo)
                if(newTapInfo) tapInfo = newTapInfo
            }
        }
        return tapInfo
    }
    intercept(interceptor){
        this.interceptors.push(interceptor);
    }
    _resetCompilation(){
        this.call = CALL_DELEGATE;
        this.callAsync = CALL_ASYNC_DELEGATE;
    }
    _insert(tapInfo){
        this._resetCompilation();
        let before = new Set();
        if(typeof tapInfo.before === 'string'){
            before = new Set([tapInfo.before])
        }else if(Array.isArray(tapInfo.before)){
            before = new Set(tapInfo.before)
        }
        //在插入的时候要按stage的顺序插入
        let stage = 0;//默认stage为0
        if(typeof tapInfo.stage === 'number'){
            stage = tapInfo.stage;
        }
        let i = this.taps.length;//总长度为3
        while(i>0){
            i--;
            const x = this.taps[i];//stage 5
            this.taps[i+1] = x;
            const xStage = x.stage || 0;
            if(before){
                if(before.has(x.name)){
                    before.delete(x.name)
                    continue
                }
                if(before.size>0) continue;
            }
            if(xStage>stage){
                continue //继续后边的循环不再进入
            }
            i++
            break;//退出
        }
        this.tap[i] = tapInfo;
     }
    compile(options){
        throw newError('抽象：应该被子类重写')
    }
    _createCall(type){
        return this.compile({
            taps:this.taps,
            args:this.args,
            interceptors:this.interceptors,//把拦截器也传过去，用来拼函数体
            type
        })
    }
    //运行注册拦截器
    _runRegisterInterceptors(tapInfo){
        for(const interceptor of this.interceptors){
            if(interceptor.register){
                let newTapInfo = interceptor.register;
                if (newTapInfo){
                    tapInfo = newTapInfo;
                }
            }
        }
        return tapInfo
    }
}
const CALL_DELEGATE = function(...args) {
    this.call = this._createCall('sync');//调用它的时候，它会动态创建call函数，重写this.call属性
    return this.call(...args);//执行新创建的call方法
}
module.exports = Hook;